package com.zjzywl.smoke.controller;

import java.io.IOException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.websocket.server.PathParam;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.zjzywl.smoke.authenticate.AuthUser;
import com.zjzywl.smoke.config.BaseDataConfig;
import com.zjzywl.smoke.manager.AlarmManager;
import com.zjzywl.smoke.repository.AlarmRepository;
import com.zjzywl.smoke.repository.AlarmTypeRepository;
import com.zjzywl.smoke.repository.DeviceRepository;
import com.zjzywl.smoke.repository.DeviceStatusHistoryRepository;
import com.zjzywl.smoke.repository.DeviceStatusRepository;
import com.zjzywl.smoke.repository.YoyRepository;
import com.zjzywl.smoke.service.DeviceService;
import com.zjzywl.smoke.service.DeviceStatusService;
import com.zjzywl.smoke.util.DataUill;
import com.zjzywl.smoke.util.MQWebSocket;
import com.zjzywl.smoke.util.WebResult;
import com.zjzywl.smoke.entity.Alarm;
import com.zjzywl.smoke.entity.AlarmType;
import com.zjzywl.smoke.entity.Device;
import com.zjzywl.smoke.entity.DeviceStatus;
import com.zjzywl.smoke.entity.DeviceStatusHistory;
import com.zjzywl.smoke.entity.SysUser;
import com.zjzywl.smoke.entity.Yoy;

@RestController
@RequestMapping(value = "/deviceStatus")
public class DeviceStatusController extends BaseController {

	@Autowired
	private DeviceStatusService deviceStatusService;

	@Autowired
	private DeviceService deviceService;

	@Autowired
	private DeviceStatusHistoryRepository deviceStatusHistoryRepository;

	@Autowired
	private AlarmTypeRepository alarmTypeRepository;

	@Autowired
	private AlarmRepository alarmRepository;

	@Autowired
	private AlarmManager alarmManager;
	@Autowired
	private AlarmRepository repository;
	@Autowired
	private YoyRepository yoyrepository;
	DataUill dataUtil = new DataUill();

	// 根据设备编码获取设备
	@RequestMapping(value = "/get/code/{devicecode}")
	@ResponseBody
	public WebResult getByCode(@PathVariable("devicecode") String devicecode) {
		Device device = deviceService.findByDeviceCode(devicecode);
		if (device != null) {
			return WebResult.OK(device);
		} else {
			return WebResult.FAIL("找不到设备信息");
		}
	}

	/*
	 * 根据设备类型及用户信息获取设备状态数据
	 */
	@RequestMapping(value = "/data/list/bydevicetype/{devicetypeId}/{userId}/{status}/{devCode}")
	public WebResult getDSByDeviceTypeAndUser(@PathVariable("devicetypeId") String devicetypeId,
			@PathVariable("userId") String userId, @PathVariable("status") String status,
			@PathVariable("devCode") String devCode) {
		List dss = deviceStatusService.getDSByUserAndDeviceType(userId, devicetypeId, status, devCode);
		return WebResult.OK(dss);
	}

	/*
	 * 根据设备类型及用户信息获取设备状态数据
	 */
	@RequestMapping(value = "/data/count/bydevicetype/{devicetypeId}/{userId}/{status}/{devCode}")
	public WebResult getDCDeviceTypeAndUser(@PathVariable("devicetypeId") String devicetypeId,
			@PathVariable("userId") String userId, @PathVariable("status") String status,
			@PathVariable("devCode") String devCode) {
		List dss = deviceStatusService.getDSByUserAndDeviceType(userId, devicetypeId, status, devCode);
		return WebResult.OK(dss.size());
	}

	// 统计异常设备上报信息
	@RequestMapping(value = "/count/bydevicetype/{status}/{devicetypeid}/{userId}/{startTime}/{endTime}/{devCode}")
	@ResponseBody
	public WebResult getCountByStatusAndDeviceTypeAndUser(@PathVariable("status") String status,
			@PathVariable("devicetypeid") String devicetypeid, @PathVariable("startTime") String startTime,
			@PathVariable("userId") String userId, @PathVariable("endTime") String endTime,
			@PathVariable("disposePeople") String disposePeople, @PathVariable("devCode") String devCode) {
		List devices = alarmRepository.getDSCountByUserAndDeviceTypeAndStatus(userId, status, devicetypeid, startTime,
				endTime, disposePeople, devCode);
		try {
			return WebResult.OK(devices);
		} catch (Exception e) {
			return WebResult.FAIL(e.getMessage());
		}
	}

	// 获取烟感实时状态数据，并调用websocket发送到前端
	@RequestMapping(value = "/push/{devCode}/{status}/{time}", method = RequestMethod.GET)
	public void receiveStatus(@PathVariable("devCode") String devCode, @PathVariable("status") Integer status,
			@PathVariable("time") String returnTime) throws ParseException, IOException, InterruptedException {
		/*
		 * 接收设备状态数据 DevEUI:设备唯一编号 status:设备状态 returnTime:上报时间 data:上报的原始串数据
		 *
		 * 1、筛选数据 2、存储记录到实时数据表 3、存储记录到历史记录表 4、通过websocket同步数据
		 */
		Device device = deviceService.findByDeviceCode(devCode);
		if (device == null) {
			System.out.println("找不到编号为：[" + devCode + "]的设备");
			return;
		}
		System.out.println("收到编号为:[" + devCode + "]设备状态：" + status);
		double getDistance = 0.0;
		// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		// Date time = format.parse(returnTime); //上报上来的时间数据很多不正常，因此注释

		// 保存历史状态信息
		DeviceStatusHistory dsh = new DeviceStatusHistory();
		dsh.setDevCode(devCode);
		dsh.setDevice(device);
		dsh.setHumidity("0");
		dsh.setTemperature1("0");
		dsh.setReturnTime(new Date());
		dsh.setStatus(status);
		dsh.setLight("0");
		dsh.setVoltage("0");
		dsh.setSpace("0");
		dsh.setTemperature("0");
		deviceStatusHistoryRepository.save(dsh);

		// 2为静音操作，9为自检操作，不是特定状态，因此只是历史信息表中存储，不作为实时状态信息存储到状态表及修改地图当前状态
		if ((status == BaseDataConfig.GS517_SMOKE_DS_SILENCE) || (status == BaseDataConfig.GS517_SMOKE_DS_SELFTEST)) {
			return;
		}
		DeviceStatus findByDevCode = deviceStatusService.findByDevCode(devCode);
		int fireCount = findByDevCode.getFireCount();

		// 保存状态信息
		DeviceStatus ds = new DeviceStatus();
		ds.setDevCode(devCode);
		ds.setDevice(device);
		ds.setHumidity("0");
		ds.setTemperature1("0");
		ds.setReturnTime(new Date());
		ds.setStatus(status);
		ds.setLight("0");
		ds.setVoltage("0");
		ds.setSpace("0");
		ds.setTemperature("0");
		ds.setFireCount(fireCount);// 将来把这一行注释掉
		if (status == 1) {
			ds.setFireCount(++fireCount);
			deviceService.updateFirCount(devCode, fireCount);
		} else {
			ds.setFireCount(fireCount);
		}

		// 更新状态信息
		deviceStatusService.deleteByDevCode(devCode);
		deviceStatusService.save(ds);
		// BaseDataConfig.GS517_SMOKE_DS_FIRE;
		// 设备报警编码转为系统报警编码
		String alarmCode = "";
		Integer alarmId = 0;
		switch (status) {
		case 1: {
			alarmCode = BaseDataConfig.ALARM_FIRE;
			break;
		}
		case 3: {
			alarmCode = BaseDataConfig.ALARM_TROUBLE;
			break;
		}
		case 4: {
			alarmCode = BaseDataConfig.ALARM_LOW;
			break;
		}
		case 7: {
			// 设置该设备所有报警信息结束时间，并从列表中移除
			alarmManager.backToNormal(devCode);
		}
		default:
			alarmCode = "";
		}

		// 如果是报警数据，保存报警数据
		if (alarmCode != "") {
			AlarmType alarmType = alarmTypeRepository.findByAlarmCode(alarmCode);
			if (alarmType == null) {
				System.out.println("找不到编号为[" + alarmCode + "]的报警类型");
				return;
			}
			Alarm alarm = new Alarm(device, alarmType);
			alarm.setAddress(device.getAddress());
			alarm.setDevice(device);
			alarm.setBeginTime(new Date());
			alarm.setDisposeStatus(0);
			Alarm am = alarmRepository.save(alarm);
			alarmId = am.getAlarmId();

			// 加入到报警队列中
			alarmManager.occurAlarm(am);
		}
		// if(status==1) {
		// AuthUser loginUser = this.getLoginUser();
		// SysUser people = loginUser.getPeople();
		// String disposePeople = people.getName();
		// calculateYOY(1,disposePeople);
		// calculateYOYByMonth(1,disposePeople);
		// calculateYOYByQuarter(1,disposePeople);
		// }
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		java.util.Date date = new java.util.Date();
		String strDate = sdf.format(date);
		if (status == 1) {
			List<DeviceStatus> findNeighPosition = findNeighPosition(ds.getDevice().getLongitude(),
					ds.getDevice().getLatitude());
			findNeighPosition.add(ds);
			for (DeviceStatus dss : findNeighPosition) {
				getDistance = GetDistance(ds.getDevice().getLatitude(), ds.getDevice().getLongitude(),
						dss.getDevice().getLatitude(), dss.getDevice().getLongitude());

				// 发送信息
				MQWebSocket.sendInfo(BaseDataConfig.CMD_SENDALARM + "," + dss.getDevice().getDevCode() + ","
						+ dss.getStatus().toString() + "," + dss.getStatusStr() + "," + dss.getDevice().getLatitude()
						+ "," + dss.getDevice().getLongitude() + "," + dss.getDevice().getDeviceName() + ","
						+ dss.getDevice().getAddress() + "," + strDate + "," + dss.getDevice().getLinkMain1() + ","
						+ dss.getDevice().getLinkPhone1() + "," + dss.getDevice().getLinkMain2() + ","
						+ dss.getDevice().getLinkPhone2() + "," + dss.getDevice().getLinkMain3() + ","
						+ dss.getDevice().getLinkPhone3() + "," + dss.getDevice().getLinkMain4() + ","
						+ dss.getDevice().getLinkPhone4() + "," + alarmId.toString() + "," + dss.getFireCount() + ","
						+ getDistance);
			}
		}
		// 发送信息
		MQWebSocket.sendInfo(
				BaseDataConfig.CMD_SENDALARM + "," + ds.getDevice().getDevCode() + "," + ds.getStatus().toString() + ","
						+ ds.getStatusStr() + "," + ds.getDevice().getLatitude() + "," + ds.getDevice().getLongitude()
						+ "," + ds.getDevice().getDeviceName() + "," + ds.getDevice().getAddress() + "," + strDate + ","
						+ ds.getDevice().getLinkMain1() + "," + ds.getDevice().getLinkPhone1() + ","
						+ ds.getDevice().getLinkMain2() + "," + ds.getDevice().getLinkPhone2() + ","
						+ ds.getDevice().getLinkMain3() + "," + ds.getDevice().getLinkPhone3() + ","
						+ ds.getDevice().getLinkMain4() + "," + ds.getDevice().getLinkPhone4() + ","
						+ alarmId.toString() + "," + ds.getFireCount() + "," + getDistance);

	}

	// 计算目标范围点附近的设备
	public List<DeviceStatus> findNeighPosition(double longitude, double latitude) {
		// 先计算查询点的经纬度范围
		double r = 6371.393;// 地球半径千米
		double dis = 0.5;// 0.5千米距离
		double dlng = 2 * Math.asin(Math.sin(dis / (2 * r)) / Math.cos(latitude * Math.PI / 180));
		dlng = dlng * 180 / Math.PI;// 角度转为弧度
		double dlat = dis / r;
		dlat = dlat * 180 / Math.PI;
		double minlat = latitude - dlat;
		double maxlat = latitude + dlat;
		double minlng = longitude - dlng;
		double maxlng = longitude + dlng;

		List<DeviceStatus> list = deviceStatusService.getDeviceByPosition(minlat, maxlat, minlng, maxlng);
		return list;
	}

	// 计算两个坐标点距离
	public static double GetDistance(double lat1, double lng1, double lat2, double lng2) {
		double radLat1 = rad(lat1);
		double radLat2 = rad(lat2);
		double a = radLat1 - radLat2;
		double b = rad(lng1) - rad(lng2);
		double s = 2 * Math.asin(Math.sqrt(
				Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
		s = s * EARTH_RADIUS;
		s = Math.round(s * 1000);
		return s;
	}

	private static double rad(double d) {
		return d * Math.PI / 180.0;
	}

	private static double EARTH_RADIUS = 6371.393;

	// 存入一周报警同比
	private void calculateYOY(int alarmTypeId, String disposePeople) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
		Date currentTime = dataUtil.getCurrentTime();// 当前时间
		System.out.println("当前时间:" + format.format(currentTime));
		Date beforeCurrentTime = dataUtil.getBeforeWeekCurrentTime();// 上周当前时间
		System.out.println("上周的当前时间:" + format.format(beforeCurrentTime));

		Date CurrentWeekTime = dataUtil.getBeginDayOfWeek();
		Date beforeCurrentWeekTime = dataUtil.getBeforeWeekBeginDayOfWeek();
		System.out.println("上周一时间:" + format.format(beforeCurrentWeekTime));
		int secondCount = repository.findByBeginTime(CurrentWeekTime, currentTime, alarmTypeId, disposePeople);
		int firstCount = repository.findByBeginTime(beforeCurrentWeekTime, beforeCurrentTime, alarmTypeId,
				disposePeople);
		Yoy yoy = new Yoy();
		DecimalFormat df = new DecimalFormat("#.00");

		if (secondCount == 0) {
			yoy.setValue(Double.parseDouble(df.format(-firstCount)));
		} else if (firstCount == 0) {
			yoy.setValue(Double.parseDouble(df.format(secondCount)));
		} else {

			yoy.setValue(Double.parseDouble(df.format((secondCount - firstCount) / (double) firstCount)));
		}
		yoy.setType("一周总报警数同比" + disposePeople);
		yoy.setFirstCount(firstCount);
		yoy.setSecondCount(secondCount);
		yoyrepository.deleteByType("一周总报警数同比" + disposePeople);
		yoyrepository.save(yoy);
	}

	// 存入一月报警同比时间
	private void calculateYOYByMonth(int alarmTypeId, String disposePeople) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
		Date currentTime = dataUtil.getCurrentTime();// 当前时间
		System.out.println("当前时间:" + format.format(currentTime));

		DecimalFormat df = new DecimalFormat("#.00");
		Date beforeCurrentTime = dataUtil.getBeforeMonthCurrentTime();// 上月当前时间
		System.out.println("上月的当前时间:" + format.format(beforeCurrentTime));

		Date CurrentMonthTime = dataUtil.getTimesMonthmorning();
		System.out.println("本月一号时间:" + format.format(CurrentMonthTime));
		Date beforeCurrentMonthTime = dataUtil.getBeginDayOfLastMonth();
		System.out.println("上月一号时间:" + format.format(beforeCurrentMonthTime));
		int secondCount = repository.findByBeginTime(CurrentMonthTime, currentTime, alarmTypeId, disposePeople);
		int firstCount = repository.findByBeginTime(beforeCurrentMonthTime, beforeCurrentTime, alarmTypeId,
				disposePeople);
		Yoy yoy = new Yoy();
		if (secondCount == 0) {
			yoy.setValue((Double.parseDouble(df.format(-firstCount))));
		} else if (firstCount == 0) {
			yoy.setValue(Double.parseDouble(df.format(secondCount)));
		} else {

			yoy.setValue(Double.parseDouble(df.format((secondCount - firstCount) / (double) firstCount)));
		}
		yoy.setType("一月总报警数同比" + disposePeople);
		yoy.setFirstCount(firstCount);
		yoy.setSecondCount(secondCount);
		yoyrepository.deleteByType("一月总报警数同比" + disposePeople);
		yoyrepository.save(yoy);
	}

	// 存入一季度报警同比时间
	private void calculateYOYByQuarter(int alarmTypeId, String disposePeople) {
		DecimalFormat df = new DecimalFormat("#.00");
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
		Date currentTime = dataUtil.getCurrentTime();// 当前时间
		System.out.println("当前时间:" + format.format(currentTime));
		Date beforeCurrentTime = dataUtil.getBeforeQuarterCurrentTime();// 上季度当前时间
		System.out.println("上季度的当前时间:" + format.format(beforeCurrentTime));
		Date CurrentQuarterTime = dataUtil.getCurrentQuarterStartTime();
		System.out.println("当季度的第一天:" + format.format(CurrentQuarterTime));
		Date beforeCurrentQuarterTime = dataUtil.getBeforeQuarterStartTime();
		System.out.println("上季度的第一天:" + format.format(beforeCurrentQuarterTime));
		int secondCount = repository.findByBeginTime(CurrentQuarterTime, currentTime, alarmTypeId, disposePeople);
		int firstCount = repository.findByBeginTime(beforeCurrentQuarterTime, beforeCurrentTime, alarmTypeId,
				disposePeople);
		System.out.println("select count(*) from Alarm u where u.beginTime>=:" + CurrentQuarterTime
				+ " and u.beginTime <=:" + currentTime + " AND alarmType.alarmTypeId=:" + alarmTypeId
				+ " and u.disposePeople=:" + disposePeople + "");
		System.out.println("select count(*) from Alarm u where u.beginTime>=:" + beforeCurrentQuarterTime
				+ " and u.beginTime <=:" + beforeCurrentTime + " AND alarmType.alarmTypeId=:" + alarmTypeId
				+ " and u.disposePeople=:" + disposePeople + "");
		Yoy yoy = new Yoy();
		if (secondCount == 0) {
			yoy.setValue(Double.parseDouble(df.format(-firstCount)));
		} else if (firstCount == 0) {
			yoy.setValue(Double.parseDouble(df.format(secondCount)));
		} else {

			yoy.setValue((Double.parseDouble(df.format((secondCount - firstCount) / (double) firstCount))));
		}
		yoy.setType("一季度总报警数同比" + disposePeople);
		yoy.setFirstCount(firstCount);
		yoy.setSecondCount(secondCount);
		yoyrepository.deleteByType("一季度总报警数同比" + disposePeople);
		yoyrepository.save(yoy);
	}
}